home *** CD-ROM | disk | FTP | other *** search
/ PC Format (UK) 124 / pcfcd124-a.iso / Trial Software / BlitzBasic / Rift2001-05-16 / Rift2 / tutorial2a-complete.bb < prev    next >
Encoding:
Text File  |  2001-05-16  |  17.7 KB  |  351 lines

  1. AppTitle "Celestial Rift - Version 1.1 (C)2001 Myke P" ;what this program will be called in MICROSOFT WINDOWS.
  2.  
  3. ;This makes two CONSTants. These are values which will NOT change at any point in the program, so we set their values now.
  4. Const SCREEN_WIDTH = 800
  5. Const SCREEN_HEIGHT = 600
  6. ;This is the code which tells Blitz what Display Resolution to use on the Graphics Card. The "GRAPHICS" command should always be placed before you do
  7. ;*anything* image-related in your program
  8. Graphics SCREEN_WIDTH,SCREEN_HEIGHT,0,1    ;start the graphics mode at SCREEN_WIDTH by SCREEN_HEIGHT, let Blitz choose the depth (,0) and run full screen (,1)
  9.  
  10. ;more program CONSTants..
  11. Const GAME_AREA_X = 50000    ;these two set the size of the map. You *should* keep them the same, 'cos the radar is square
  12. Const GAME_AREA_Y = 50000    ;but technically, you can change the values to anything you like! ;)
  13. ;the following constants are keyboard "SCAN" codes. Every key on the keyboard has a number. You can get the full list in your Blitz manual.
  14. Const KEY_CLOCKWISE = 25    ;(p)    
  15. Const KEY_ANTICWISE = 24    ;(o)
  16. Const KEY_SPEEDUP = 16        ;(q)
  17. Const KEY_SPEEDDOWN = 30    ;(a)
  18. Const KEY_FIRE = 57            ;(Space)
  19. Const KEY_QUIT = 1            ;(Escape)
  20. Const KEY_PAUSE = 7            ;(Number 6 on the main keyboard)
  21. Const KEY_DEBUG = 59        ;(F1)
  22. Const KEY_SAVESCREEN = 88    ;(F12)
  23. ;the following constants affect the way the game plays. Feel free to mess with the values..
  24. Const INCR_ROTATE# = 5                ;.. but DON'T touch this, otherwise the game will crash (I only drew the animation frames for 5 degree intervals!)
  25. Const INCR_SPEED# = 0.5
  26. Const INCR_SLOW# = 0.125
  27. Const SPEED_MAX = 25
  28. Const SPEED_MIN = -5
  29.  
  30. ;set up changable variables for game/menu (with initial values, if you like - i.e.: you could just as soon as set them later!)
  31. Global FLAG_GAMEON = 1
  32. Global FLAG_PAUSE
  33. Global FLAG_SAVESCREEN = 0
  34. Global FLAG_DEBUG = 0
  35. Global FLAG_GAMESTARTER
  36. Global PLAYER_SHIELD#
  37. Global PLAYER_SPEED#
  38. Global PLAYER_ANGLE#
  39. Global PLAYER_X#
  40. Global PLAYER_Y#
  41.  
  42. Global timer
  43. Global frames
  44. Global starson
  45. Global game_pause_frame
  46. Global game_accept_pause
  47. Global game_pause_stat
  48. ;a "#" symbol after the variable name means it can hold a FLOATING POINT number, i.e.: 190.1234
  49. ;without the "#" symbol, the variable is, by default, an INTEGER (Whole) number, i.e.: 190
  50. ;use the symbols when you are *sure* that you want it to hold specific types of data:
  51. ;# - floating point
  52. ;% - integer (whole number)
  53. ;$ - string (text, i.e.: "MYKE 12345"
  54. Global tempstr$
  55.  
  56. timer = CreateTimer(50) ;create a timer set at 50ms (game speed) - play with this to see how you can increase or decrease the speed of the game.
  57.                         ;this should be set at a speed which will look near enough the same on *every* PC it will be played on.
  58.                         ;My PC (a 733MHz PIII with an nVidia GeForce card) will handle upwards of 150 frames per second, quite happily
  59.                         ;but 'lesser' machines will not. 50, therefore, is quite sensible For a game of this nature, who's minimum system spec
  60.                         ;will be something like a PII 300MHz machine (i.e.: Blitz Basic's minimum spec!)
  61.  
  62. ;NOTE: there's no need to organise your variable declarations, as I have here, into sections. They can appear in any order you like, before the main program begins.
  63. ;I just do this, 'cos it looks right professional! :))))
  64.  
  65. ;picture/animation (and related) variables
  66. Dim game_stars(5)            ;these 3 are ARRAYS. An array is automatically Global, but requires the Keyword (Yellow bit) DIM instead. This means "Dimension".
  67. Global game_player
  68. Global game_player_frame
  69. Global game_gameover
  70. Global game_paused
  71.  
  72. ;Types are like Structures in C. You have a "Type" called whatever. Then you can make multiple versions of the type. Each version of the Type has the same properties, i.e.:
  73. ;a FISH (the Type) has EYES, MOUTH, SCALES And FINS (it's properties) - ALL FISH have these properties.
  74. ;a DOG (the Type) has EYES, MOUTH, FUR and TAIL (it's properties) - ALL DOGS have these properties (look like this.)
  75. Type stars                        ;create "Type" for parallex stars
  76.     Field depth,x#,y#            ;each star has a depth, x and y position
  77. End Type
  78.  
  79. menustars = SCREEN_HEIGHT/3 ;generate a number of stars, so that they look dense enough on all test resolutions
  80. starson = 1 ;tells the program to show the stars (see later)
  81. For i=0 To menustars                    ;create <menustars> number of stars in the STARS type
  82.     star.stars=New stars                ;add a new star for each increment of i
  83. Next
  84.  
  85. ;this code loads the image numbers into an array called "game_ stars", which we DIMmed earlier. It has 6 containers (0,1,2,3,4,5) but I'm only using 1 to 5!
  86. ;an "image number" is what Blitz uses to reference graphics held in the Video Memory, i.e.:
  87. ;1. Image number 12 is a picture of a flower.
  88. ;2. Make a variable called "flower_pic" = 12
  89. ;3. Wherever Blitz is told to draw "flower_pic", reference image number 12 in the Video Memory.
  90. game_stars(1) = LoadImage("GfxRes/backg-star-1.bmp")    ;container (1) in "game_stars" holds the image number for this picture ("GfxRes/backg-star-1.bmp")
  91. game_stars(2) = LoadImage("GfxRes/backg-star-2.bmp")    ;etc..
  92. game_stars(3) = LoadImage("GfxRes/backg-star-3.bmp")
  93. game_stars(4) = LoadImage("GfxRes/backg-star-4.bmp")
  94. game_stars(5) = LoadImage("GfxRes/backg-star-5.bmp")
  95. For i = 1 To 5
  96.     MaskImage game_stars(i),255,0,255    ;mask the images for each star, so that MAGENTA (255,0,255) is the transparent colour
  97. Next
  98.  
  99. ;notice in the following code, we're loading (and MASKING) graphics in exactly the same way as before, but into regular variables instead of arrays.
  100. ;this next bit is all animations
  101. game_player = LoadAnimImage("GfxRes/player-ship.bmp",80,80,0,72) ;load in the 'sprite' for the player ship
  102. MaskImage game_player,255,0,255 ;mask the images for the player ship, so that MAGENTA (255,0,255) is the transparent colour
  103. ;these are all plain single-frame pictures
  104. ;game piccies
  105. game_gameover = LoadImage("GfxRes/game-gameover.bmp")        ;the game over logo, which I tend to see a lot of.. :(
  106. game_paused = LoadImage("GfxRes/game-paused.bmp")            ;the paused logo
  107. MaskImage game_gameover,255,0,255
  108. MaskImage game_paused,255,0,255
  109.  
  110. ;Right! That's it, we've set up *everything* we're going to need from outside the program. Let's start up the game_loop function..
  111. game_loop()
  112.  
  113. ;this function keeps the game loop going.. It starts playing tunes and sets a couple of variables. 
  114. ;Then it goes into a never ending loop which carries out a sequence of checks and function calls, until such time as we want to stop it!
  115. Function game_loop()
  116.     FLAG_GAMEON = 1 ;tells the program that the game is running.
  117.     game_initialise()     ;calls a function called "game_initialise()" (which is next in the code) which
  118.                         ;just gives the player full energy and a score of 0 etc..)
  119.     Repeat        ;as with the menu, we want to cycle though the process of updating/drawing forever, until such time as the game has ended.
  120.         If FLAG_GAMEON = 1 Then        ;.. so, if FLAG_GAMEON is 1, then "do" the following.
  121.             game_loop_update()                                ;call the game_loop_update() function
  122.         Else
  123.             FlushKeys                
  124.             End                    ;if FLAG_GAMEON isn't 1, we End the program
  125.         End If
  126.     Forever
  127. End Function
  128.  
  129. ;As described a minute ago, this function sets up the game variables as they should be
  130. ;at the start of every game, i.e.: Player Shields are full, the score is 0 etc..
  131. Function game_initialise()
  132.     FLAG_DEBUG = 1                    
  133.     FLAG_GAMESTARTER = 1
  134.     FLAG_PAUSE = 0
  135.     PLAYER_ANGLE = 0
  136.     PLAYER_SPEED = 0
  137.     game_player_randomize()            ;calls a function that randomizes a player's position on the map
  138.     game_stars_randomize()            ;calls a function that randomizes the star positions
  139.  
  140. End Function
  141.  
  142. ;once again, like it's menu equivalent, "game_loop_update()" is a function which analyses player input, working out all the new
  143. ;coordinate positions and anything else which needs deciding before updating the screen display.
  144. Function game_loop_update()
  145.     frames = WaitTimer(timer)
  146.     For i = 1 To frames
  147.         If KeyDown(KEY_PAUSE)                                    ;checks to see if the user has pressed the "PAUSE" key
  148.             FlushKeys
  149.             If game_accept_pause = 1                            ;the "game_accept_pause" variable is used in the same way as "menu_accept_quit" earlier.
  150.                                                                 ;because we're using SCANCODES, the program will register a number of qualifying cases where
  151.                                                                 ;when this check is performed, the key is still held down (at 50 frames per second, if the user
  152.                                                                 ;held down the key for half a second, the KEYDOWN function would fire around 25 times!)
  153.                                                                 
  154.                 If FLAG_PAUSE = 0 Then                            ;If FLAG_PAUSE is 0 then..
  155.                     FLAG_PAUSE = 1                                ;make FLAG_PAUSE = 1
  156.                     game_accept_pause = 0                        ;don't accept any more "PAUSE" button presses until "game_accept_pause" is set back to 1
  157.                     game_pause_frame = 1                        ;make "game_pause_frame" = 1 which, similarly to "menu_frame" earlier will enable the flashing of "PAUSED".
  158.                 Else
  159.                     FLAG_PAUSE = 0                                ;If FLAG_PAUSE isn't 0 (the game was paused) then..
  160.                     game_accept_pause = 0                        ;do exactly the same, but set FLAG_PAUSE to 0.
  161.                     game_pause_frame = 1
  162.                 End If
  163.             End If
  164.         End If
  165.         If KeyDown(KEY_SAVESCREEN)        ;If the "SCREENSAVE" button is pressed..
  166.             FlushKeys                    ;this functions exactly the same as in menu_loop_update()
  167.             FLAG_SAVESCREEN = 1
  168.         End If
  169.         If KeyDown(KEY_QUIT)        ;If the "QUIT" button is pressed..
  170.             FlushKeys
  171.             FLAG_GAMEON=0             ;set FLAG_GAMEON to equal 0. Back in the "game_loop()" function, this will cause the code to jump back to the menu.
  172.         End If
  173.  
  174.         If FLAG_PAUSE = 0 Then                            ;this is really easy! If the game is paused then *don't* do any of the following code. No values will change,
  175.                                                         ;hence nothing will move on the screen when it comes to updating it later! :)
  176.                                                         
  177.                 If KeyDown(KEY_CLOCKWISE)                            ;if "CLOCKWISE" key is pressed then..
  178.                     PLAYER_ANGLE = PLAYER_ANGLE + INCR_ROTATE            ;Add "INCR_ROTATE" degrees to the current PLAYER_ANGLE
  179.                     FlushKeys
  180.                     If PLAYER_ANGLE >= 360 Then                            ;if the PLAYER_ANGLE is 360, then reset it to 0.
  181.                         PLAYER_ANGLE = PLAYER_ANGLE - 360
  182.                     End If
  183.                 End If
  184.                 If KeyDown(KEY_ANTICWISE)                            ;exactly the same, but Subtract "INCR_ROTATE" from the player angle and
  185.                     PLAYER_ANGLE = PLAYER_ANGLE - INCR_ROTATE        ;reset it to (for example) 355, if the angle is -5.
  186.                     FlushKeys
  187.                     If PLAYER_ANGLE < 0 Then
  188.                         PLAYER_ANGLE = PLAYER_ANGLE + 360
  189.                     End If
  190.                 End If
  191.                 If KeyDown(KEY_SPEEDUP) Then                        ;if the "SPEEDUP" key is pressed.
  192.                     If PLAYER_SPEED < SPEED_MAX                            ;as long as the player speed is less than the maximum speed (SPEED_MAX), then
  193.                         PLAYER_SPEED = PLAYER_SPEED + INCR_SPEED        ;Add "INCR_SPEED" to the player's speed value
  194.                         FlushKeys
  195.                     Else
  196.                         PLAYER_SPEED = PLAYER_SPEED - INCR_SLOW            ;if the PLAYER_SPEED is not less than the maximum speed then take "INCR_SLOW" off of it!
  197.                         FlushKeys
  198.                     End If
  199.                 Else                                                ;if the key isn't being pressed, then..
  200.                     If PLAYER_SPEED > 0 Then                            ;as long as the player speed is greater than 0, then take "INCR_SLOW" off the current value
  201.                         PLAYER_SPEED = PLAYER_SPEED - INCR_SLOW            ;(this is an easy "No power" decelaration for the space ship)
  202.                     End If
  203.                     FlushKeys
  204.                 End If
  205.                 If KeyDown(KEY_SPEEDDOWN)                            ;exactly the same thing, but with the ship's thrusters in reverse! :)
  206.                     If PLAYER_SPEED > SPEED_MIN
  207.                         PLAYER_SPEED = PLAYER_SPEED - INCR_SPEED
  208.                         FlushKeys
  209.                     Else
  210.                         PLAYER_SPEED = SPEED_MIN
  211.                         FlushKeys
  212.                     End If
  213.                 Else
  214.                     If PLAYER_SPEED < 0 Then
  215.                         PLAYER_SPEED = PLAYER_SPEED + INCR_SLOW
  216.                     End If
  217.                 End If
  218.                 
  219.                 ;this next peice of code updates the player position on the map, relative to it's Speed and Angle and it's last position
  220.                 PLAYER_X = PLAYER_X + (PLAYER_SPEED*(Sin(PLAYER_ANGLE)/2))
  221.                 PLAYER_Y = PLAYER_Y - (PLAYER_SPEED*(Cos(PLAYER_ANGLE)/2))
  222.                 If PLAYER_X < 0 Then                        ;if the PLAYER_X value is less than 0, then wrap your position around the map
  223.                     PLAYER_X = (PLAYER_X + GAME_AREA_X)        ;by adding the GAME_AREA_X value to the negative value, i.e.: -5 becomes 19995 on a 20000 X pixel map.
  224.                 End If
  225.                 If PLAYER_X > GAME_AREA_X Then                ;the same in reverse, i.e. 20004 becomes 4 on the same map.
  226.                     PLAYER_X = (PLAYER_X - GAME_AREA_X)
  227.                 End If
  228.                 If PLAYER_Y < 0 Then                        ;and now the same for the Y direction
  229.                     PLAYER_Y = (PLAYER_Y + GAME_AREA_Y)
  230.                 End If
  231.                 If PLAYER_Y > GAME_AREA_Y Then
  232.                     PLAYER_Y = (PLAYER_Y - GAME_AREA_Y)
  233.                 End If
  234.             
  235.  
  236.             ;the parralex stars move relative to the player and is just the same "menustars" number of stars
  237.             ;scrolled at various speeds, wrapping around the screen.
  238.             ;it's a fairly cheap, but effective way of creating a nice illusion of speed!
  239.             If starson=1 Then                ;if, at the beginning of the program, you set "starson" to 0, the stars will disappear.
  240.                                             ;the game would also feel pretty bloody wierd.. hold on.. yep.. Absolutely mad! Try it! :)
  241.                 For star.stars=Each stars
  242.                     ;the following two lines move each version of the "stars" Type an x and y distance relative to the player's speed and angle
  243.                     ;with a devision relative to the depth of the star to make the smallest stars move slower than the biggest
  244.                     ;thus we have our parallex effect.
  245.                     
  246.                     ;it might be of interest to know that these two lines were based on the OLDSKOOL demo which comes with Blitz Basic
  247.                     ;and was the starting point for the whole CELESTIAL RIFT game concept! Thanks a lot, Mr Mikkel L°kke!! :)
  248.                     star\y=(star\y+PLAYER_SPEED*(Cos(360-PLAYER_ANGLE)/(6-star\depth+1)))
  249.                     star\x=(star\x+PLAYER_SPEED*(Sin(360-PLAYER_ANGLE)/(6-star\depth+1)))
  250.                     ;the maximum pixel width of for the biggest star image is 5 pixels
  251.                     ;the following IF statements wrap the stars around the screen border when they reach the extremities
  252.                     If star\x < -5 Then
  253.                         star\x = star\x + (SCREEN_WIDTH + 5)
  254.                     End If
  255.                     If star\x > SCREEN_WIDTH Then
  256.                         star\x = star\x - (SCREEN_WIDTH + 5)
  257.                     End If
  258.                     If star\y <= -5 Then
  259.                         star\y = star\y + (SCREEN_HEIGHT + 5)
  260.                     End If
  261.                     If star\y >= SCREEN_HEIGHT
  262.                         star\y = star\y - (SCREEN_HEIGHT + 5)
  263.                     End If
  264.                 Next
  265.             End If    ;end of the "are the stars going to be shown" IF statement
  266.  
  267.         End If ;end of "IF FLAG_PAUSE = 0" IF Statement
  268.         
  269.         ;this flashes the "PAUSED" caption on and off when needs be!
  270.         game_pause_frame = game_pause_frame + 1
  271.         If game_pause_frame = 25 Then
  272.             game_pause_frame = 1
  273.             game_accept_pause = 1
  274.             If game_pause_stat = 1 Then
  275.                 game_pause_stat = 0
  276.             Else
  277.                 game_pause_stat = 1
  278.             End If
  279.         End If
  280.  
  281.     Next    ;end of the "for i = 1 to frames" FOR loop
  282.     
  283.     game_draw_update()    ;finally, draw all the pictures on the screen, based on their (possibly) new positions.
  284. End Function
  285.  
  286. ;this function draws the game graphics in their freshly calculated positions
  287. Function game_draw_update()
  288.     SetBuffer BackBuffer()    ;draw all of the following to the backbuffer
  289.     ClsColor 0,0,0            ;changes the CLearScreen colour to black (0,0,0)
  290.     Cls
  291.     If starson=1 Then        ;draw all of the stars using their correct pictures, at the correct x and y positions
  292.         For star.stars=Each stars ;(for each star in type 'stars' do the following..)
  293.             DrawImage game_stars(star\depth),star\x,star\y    ;using the depth property of "stars" as the Array position
  294.         Next
  295.     End If
  296.     
  297.     game_player_frame = PLAYER_ANGLE/5
  298.     If game_player_frame = 72 Then
  299.         game_player_frame = 0
  300.     End If
  301.     
  302.     DrawImage game_player,(SCREEN_WIDTH/2)-ImageWidth(game_player)/2,(SCREEN_HEIGHT/2)-ImageHeight(game_player)/2,game_player_frame
  303.     
  304.     Color 255,0,255
  305.     
  306.     ;if the game is paused (FLAG_PAUSE = 1) then draw the image when "game_pause_stat" = 1
  307.     ;this gives us our flash on-off effect as used earlier in "menu_draw_update()"
  308.     
  309.     If FLAG_PAUSE = 1 And game_pause_stat = 1 Then
  310.         DrawImage game_paused,SCREEN_WIDTH/2-ImageWidth(game_paused)/2,SCREEN_HEIGHT-((SCREEN_HEIGHT-350)/2+ImageHeight(game_paused)/2)
  311.     End If
  312.     
  313.     ;the following text will only be printed on the screen while the "FLAG_DEBUG" variable is set to 1 (which for the purpose of this tutorial, we've left it at!)
  314.     If FLAG_DEBUG = 1 Then
  315.         ;the TEXT command writes a STRING of text onto the screen at the given coordinates in the currently set font
  316.         ;as I haven't used the LoadFont or SetFont commands, this will just be Blitz' default font.
  317.  
  318.         Color 255,255,255                                    ;just in case, set the colo(u)r of the text to WHITE (255, 255, 255)
  319.         Text 0,0,"PLAYER ANGLE = " + PLAYER_ANGLE                ;"Write the string 'PLAYER ANGLE = ' followed by the number held in PLAYER_ANGLE"
  320.         Text 0,20,"PLAYER SPEED = " + PLAYER_SPEED
  321.         Text 0,40,PLAYER_ANGLE + " / 5 = " + PLAYER_ANGLE/5
  322.         Text 0,60,"SHIPFRAME = " + game_player_frame
  323.         Text 0,80,"CO-ORDS = " + Int(PLAYER_X)
  324.         Text 140,80," , " 
  325.         Text 160,80,Int(PLAYER_Y)
  326.     End If
  327.     
  328.     ;just like in "menu_draw_update()", the user can press a key which just makes the value of "FLAG_SCREENSAVE" equal 1.
  329.     ;when the code gets to here, it saves out the named Buffer as a BMP picture.
  330.     If FLAG_SAVESCREEN=1 Then
  331.         SaveBuffer (BackBuffer(),"CRGameScreen.bmp")
  332.         FLAG_SAVESCREEN = 0
  333.     End If 
  334.     
  335.     Flip                    ;as before in "menu_draw_update()", FLIP everything we've just drawn on the backbuffer and show it on the frontbuffer, i.e.: your monitor!!
  336. End Function
  337.  
  338. ;a little function which randomizes the x and y coordinates of each version of the "stars" Type, plus it's "depth" property
  339. Function game_stars_randomize()
  340.     For star.stars=Each stars
  341.         star\x=Rnd(-5,SCREEN_WIDTH)            ;create random x and y positions for all the stars
  342.         star\y=Rnd(-5,SCREEN_HEIGHT)
  343.         star\depth=Rnd(1,5)                    ;the depth of the stars results in our sexy parallex effect
  344.     Next
  345. End Function
  346.  
  347. ;an even littler function which just gives us random x and y coordinates for the player.
  348. Function game_player_randomize()
  349.     PLAYER_X = Rand(0,GAME_AREA_X)
  350.     PLAYER_Y = Rand(0,GAME_AREA_Y)
  351. End Function